package info.niwota.fwrite;

import info.niwota.commons.XmppService;

import java.io.File;
import java.io.IOException;

import org.json.JSONObject;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;

/**
 * Frite - finger writer - scribble your friends a message with a finger.
 * 
 * No more typing, just scribble.
 * 
 * English, Espanol, Zhongwen, extinct or artificial.
 * 
 * Save and send via email, sms, etalk or reply via attach...
 * 
 * A todo list for yourself or warm greetings to your friends, just scribble it.
 * 
 * Feel free to write me at liqiang@gmail.com if you catch me online.
 * 
 * @author qiangli
 * 
 */
public class WriteActivity extends BaseActivity {

	private static final String TAG = "WriteActivity";
	
	private final Handler handler = new Handler();
	private final Runnable peerStatusUpdater = new Runnable() {
		public void run() {
			updateStatus();
		}
	};
	
	protected final IntentFilter intentFilter = new IntentFilter(
			XmppService.XMPP_PEER_STATUS_ACTION);

	protected int mStatus;
	
	protected final BroadcastReceiver receiver = new BroadcastReceiver() {
		public void onReceive(Context context, Intent intent) {
			if (Debug.DEBUG) {
				Log.d(TAG,
						"onReceive intent: " + intent + " extras: "
								+ intent.getExtras());
			}
			final String action = intent.getAction();
			
			if (XmppService.XMPP_PEER_STATUS_ACTION.equals(action)) {
				String peer = intent.getStringExtra(XmppService.EXTRA_PEER_ID);
				if (peer != null && peer.equals(getPeer())) {
					handler.post(peerStatusUpdater);
					mStatus = intent.getIntExtra(XmppService.EXTRA_PEER_STATUS, 0);
				}
			}
		}
	};


	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		if (Debug.DEBUG) {
			Log.d(TAG, " " + savedInstanceState);
		}
	}

	protected void updateStatus() {
		setPeerStatus(mStatus);
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			if (isPickIntent()) {
				setResult(RESULT_CANCELED);
				finish();
				return true;
			}

			cancelIfRunning();	
			doBack();
			return true;
		}
		return super.onKeyDown(keyCode, event);
	}

	@Override
	protected void onResume() {
		super.onResume();
		
		try {
			boolean picking = isPickIntent();
			
			if (Debug.DEBUG) {
				Log.d(TAG, "onResume picking: " + picking);
			}
			//
//			if (picking) {
//				Button send = (Button) findViewById(R.id.keyboard_done);
//				send.setText(R.string.keyboard_key_done);
//			}
			
			if (!picking) {
				SessionManager.writer = this;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		registerReceiver(receiver, intentFilter);
	}

	@Override
	protected void onPause() {
		super.onPause();
		
		SessionManager.writer = null;
		
		unregisterReceiver(receiver);
	}

	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		super.onPrepareOptionsMenu(menu);
		//
		boolean picking = isPickIntent();
		if (Debug.DEBUG) {
			Log.d(TAG, "onResume picking: " + picking);
		}
		MenuItem quit = (MenuItem) menu.findItem(R.id.write_quit_opt_menu_id);
		quit.setTitle(picking ? R.string.action_quit_pick
				: R.string.action_quit);
		//
		return true;
	}

	
	@Override
	protected void doSend() {
		if (isPickIntent()) {
			doAttach();
			finish();
			return;
		}
		super.doSend();
	}

	protected void doAttach() {
		try {
			File file = mDocument.capture();
			Uri uri = Utils.toUri(file);
			Intent data = new Intent(null, uri);
			data.putExtra("size", file.length());
			data.putExtra("name", file.getName());
			setResult(RESULT_OK, data);
			addImage(file);
			//
			clearDocument();
			//
			if (Debug.DEBUG) {
				Log.d(TAG, "doAttach data: " + data);
			}
		} catch (Exception e) {
			showError(e);
		}
	}

	public boolean updateElement(int type, String val, String peer) {
		final String[] obj = new String[2];
		obj[0] = val;
		obj[1] = peer;
		
		Message msg = Message.obtain(inputHandler);
	
		msg.what = type;
		msg.obj = obj;
	
		return inputHandler.sendMessage(msg);
	}
	
	public boolean updateNotification() {
		Message msg = Message.obtain(inputHandler);
		msg.what = -100;
		msg.arg1 = -2; //chat
		return inputHandler.sendMessage(msg);
	}
	
	public boolean updateStatusWriting() {
		Message msg = Message.obtain(inputHandler);
		msg.what = -100;
		msg.arg1 = -1;
		return inputHandler.sendMessage(msg);
	}
	
	public boolean updateStatusAvail() {
		Message msg = Message.obtain(inputHandler);
		msg.what = -100;
		msg.arg1 = XmppService.PEER_STATUS_AVAIL;
		return inputHandler.sendMessage(msg);
	}

	@Override
	protected void loadDocument(String peer, int status) {
		super.loadDocument(peer, status);
		
		try {
			processIncomingMessage(peer);
		} catch (IOException e) {
			showError(e);
			//
			e.printStackTrace();
		}
	}

	public void processIncomingMessage(String peer) throws IOException {
		SessionManager.processMessage(peer, this);
	}
	
	public void addElement(int type, String val, String peer) {
		if (Debug.DEBUG) {
			Log.d(TAG, type+":"+val);
		}

		switch (type) {
		case 1: 
			//key
			int id = KeyHelper.map(val);
			switch(id) {
			case R.id.keyboard_bs:
				removeElement(peer);
				break;
			case R.id.keyboard_lf:
				addLineFeed(peer);
				break;
			case R.id.keyboard_sp:
				addBlankElement(peer);
				break;
			default:
			}
			break;
		case 2: 
			//gesture
			try {
				JSONObject jo = new JSONObject(val);
				addElement(new GestureElement(jo), peer);
			} catch (Exception e) {
				showError(e);
			}
			break;
		case 3:
			//smiley
			int icon = Smiley.map(val);
			Element el = new ResourceImageElement(icon);
			addElement(el, peer);
			break;
		case 4:
			//image
			try {
				JSONObject jo = new JSONObject(val);
				addElement(new ImageElement(jo), peer);
			} catch (Exception e) {
				showError(e);
			}
			break;
		case 5:
			//text
			if (!TextUtils.isEmpty(val)) {
				String[] ta = val.split(",", 4);
				if (ta != null && ta.length == 4) {
					final int tt = parseInt(ta[0], TextElement.TYPE_PLAIN);
					final int tc = parseInt(ta[1], TextElement.DEFAULT_COLOR);
					final float ts = parseFloat(ta[2], TextElement.DEFAULT_SIZE);
					Element e = new TextElement(tt, ta[3], tc, ts);
					addElement(e, peer);
				}
			}
			break;
		default:
		}
	}

	private float parseFloat(String s, float def) {
		try {
			return Float.parseFloat(s);
		} catch (Exception e) {
			//
		}
		return def;
	}

	private int parseInt(String s, int def) {
		try {
			return Integer.parseInt(s);
		} catch (Exception e) {
			//
		}
		return def;
	}

	private Handler inputHandler = new Handler() {
		public void handleMessage(Message msg) {
			if (msg.what < 0) {
				switch(msg.what) {
				case -100:
					setPeerStatus(msg.arg1);
					break;
				default:
				}
				return;
			}
			String[] obj = (String[]) msg.obj;
			addElement(msg.what, obj[0], obj[1]);
			setPeerStatus(XmppService.PEER_STATUS_AVAIL);
		}
	};
}
